﻿using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor.Profiling;
using UnityEngine;

public class BuffManager
{
    private static BuffManager instance;
    private Dictionary<int, Dictionary<string, MethodInfo>> buffModelSet;
    private List<Type> allBuffConfigType = null;
    public static BuffManager Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new BuffManager();
                
            }
            return instance;
        }
    }

    public void Init()
    {
        if (buffModelSet == null)
        {
            buffModelSet = new Dictionary<int, Dictionary<string, MethodInfo>>();
            allBuffConfigType = new List<Type>();
            ScanAllBuffModelAndConfig();
        }

        
    }

    public void ScanAllBuffModelAndConfig()
    {
        Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
        for (int i = 0; i < assemblies.Length; i++)
        {
            Assembly assembly = assemblies[i];
            Type[] allTypes = assembly.GetTypes();
            for (int j = 0; j < allTypes.Length; j++)
            {
                Type type = allTypes[j];
                BuffModel model = type.GetCustomAttribute<BuffModel>();
                if (model != null)
                {
                    ScanSingleBuffModel(type, model);
                    continue;
                }

                BuffConfig config = type.GetCustomAttribute<BuffConfig>();
                if (config != null)
                {
                    ScanSingleBuffConfig(type);
                }
            }
        }
    }

    public void ScanSingleBuffModel(Type type, BuffModel buffModel)
    {
        // Dictionary<string, MethodInfo> methodInfoDic = new Dictionary<string, MethodInfo>();
        MethodInfo[] methodInfos = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
        for (int i = 0; i < methodInfos.Length; i++)
        {
            MethodInfo methodInfo = methodInfos[i];
            BuffProcesser processer = methodInfo.GetCustomAttribute<BuffProcesser>();
            if (processer != null)
            {
                int key = buffModel.mainType + processer.subType;
                Dictionary<string, MethodInfo> methodInfoDic = null;
                if (this.buffModelSet.ContainsKey(key))
                {
                    methodInfoDic = this.buffModelSet[key];
                }
                else
                {
                    methodInfoDic = new Dictionary<string, MethodInfo>();
                    this.buffModelSet.Add(key, methodInfoDic);
                }
                methodInfoDic.Add(processer.funcName, methodInfo);
            }
        }
    }
    
    public void ScanSingleBuffConfig(Type type)
    {
        allBuffConfigType.Add(type);
    }

    /// <summary>
    /// 创建buffNode，并将配置数据填充进去
    /// </summary>
    /// <param name="buffId"></param>
    /// <returns></returns>
    public BuffNode CreateBuffNode(int buffId)
    {
        MethodInfo methodInfo = GetProcesserFuncByBuffId(buffId, "BuffTime");
        BuffNode node = new BuffNode(buffId);
        if (methodInfo != null)
        {
            methodInfo.Invoke(null, new object[]{node}); //初始化buff time 相关的数据
        }

        return node;
    }

    /// <summary>
    /// 通关方法名，调用BuffModel对应的方法
    /// </summary>
    /// <param name="buffId">buffID</param>
    /// <param name="funcName">BuffModel 的方法名称</param>
    /// <returns></returns>
    public MethodInfo GetProcesserFuncByBuffId(int buffId, string funcName)
    {
        int mainType = (int)(buffId / 100000);
        // int subType = buffId % 100000;
        int key = mainType * 100000;
        Dictionary<string, MethodInfo> funMap = null;
        Dictionary<string, MethodInfo> defaultFunMap = null;
        key = key - 1;
        if (this.buffModelSet.ContainsKey(key))
        {
            defaultFunMap = this.buffModelSet[key];
        }
         if (this.buffModelSet.ContainsKey(buffId))
        {
            funMap = this.buffModelSet[buffId];
        }
        else
        {
            funMap = defaultFunMap;
        }

        MethodInfo m = this.GetProcesserFunc(funcName, funMap, defaultFunMap);
        return m;
    }

    private MethodInfo GetProcesserFunc(string funcName, Dictionary<string, MethodInfo> funMap, Dictionary<string, MethodInfo> defaultFunMap)
    {
        if (funMap.ContainsKey(funcName))
        {
            return funMap[funcName];
        }else if (defaultFunMap.ContainsKey(funcName))
        {
            return defaultFunMap[funcName];
        }

        return null;
    }
}